// index.ts
import axios from "axios";
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";
import {showFailToast} from "vant";
import router from "@/router";

type Result<T> = {
    code: number;
    message: string;
    result: T;
};

// 导出Request类，可以用来自定义传递配置来创建实例
export class Request {
    // axios 实例
    instance: AxiosInstance;
    // 基础配置，url和超时时间
    baseConfig: AxiosRequestConfig = { baseURL: "https://api.shop.eduwork.cn", timeout: 5000 };

    constructor(config: AxiosRequestConfig) {
        // 使用axios.create创建axios实例
        this.instance = axios.create(Object.assign(this.baseConfig, config));

        this.instance.interceptors.request.use(
            (config: any) => {
                // 一般会请求拦截里面加token，用于后端的验证
                const token = window.localStorage.getItem("token") as string
                if(token) {
                    // 如果token存在
                    // Authorization: Bearer Token ; key : value
                    // 在headers头部加上Authorization属性，把token带到服务器里面
                    config.headers.Authorization = "Bearer " + token; // Bearer 右边有一个空格
                }

                return config;
            },
            (err: any) => {
                // 请求错误，这里可以用全局提示框进行提示
                return Promise.reject(err);
            }
        );

        this.instance.interceptors.response.use(
            (res: AxiosResponse) => {
                // 直接返回res，当然你也可以只返回res.data
                // 系统如果有自定义code也可以在这里处理
                return res;
            },
            (err: any) => {
                // 这里用来处理http常见错误，进行全局提示
                if (err.code === "ERR_NETWORK" ||
                    err.code === "ECONNABORTED") {
                    showFailToast("网络错误!");
                    return;
                }
                if (err.response && err.response.status === 401) {
                    router.push({path: "/login"}).then(r => console.log(r));
                } else {
                    // 如果后端接口有错误提示消息，这里统一处理,显示错误信息
                    console.log(err);
                    // 通过err.response响应数据里面的错误，拿到Object键里面的错误信息
                    if (err.response && err.response.data && err.response.data.errors && err.response.data.errors.length > 0) {
                        showFailToast(err.response.data.errors[Object.keys(err.response.data.errors)[0]][0]);
                    }
                }
                return Promise.reject(err);
            }
        );
    }

    // 定义请求方法
    public request(config: AxiosRequestConfig): Promise<AxiosResponse> {
        return this.instance.request(config);
    }

    public get<T = any>(
        url: string,
        config?: AxiosRequestConfig
    ): Promise<AxiosResponse<T>> {
        return this.instance.get(url, config);
    }

    public post<T = any>(
        url: string,
        data?: any,
        config?: AxiosRequestConfig
    ): Promise<AxiosResponse<T>> {
        return this.instance.post(url, data, config);
    }

    public put<T = any>(
        url: string,
        data?: any,
        config?: AxiosRequestConfig
    ): Promise<AxiosResponse<Result<T>>> {
        return this.instance.put(url, data, config);
    }

    public delete<T = any>(
        url: string,
        config?: AxiosRequestConfig
    ): Promise<AxiosResponse<Result<T>>> {
        return this.instance.delete(url, config);
    }
}

// 默认导出Request实例
export default new Request({})
